package com.yuanxin.chooseimage;

import android.content.Context;
import android.content.res.AssetFileDescriptor;
import android.graphics.Bitmap;
import android.graphics.SurfaceTexture;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.os.Handler;
import android.os.Vibrator;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.ViewGroup;

import com.facebook.react.bridge.LifecycleEventListener;
import com.yuanxin.chooseimage.R;
import com.facebook.react.bridge.Arguments;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReadableArray;
import com.facebook.react.bridge.ReadableMap;
import com.facebook.react.bridge.WritableMap;
import com.facebook.react.common.MapBuilder;
import com.facebook.react.uimanager.ThemedReactContext;
import com.facebook.react.uimanager.ViewGroupManager;
import com.facebook.react.uimanager.annotations.ReactProp;
import com.facebook.react.uimanager.events.RCTEventEmitter;
import com.google.zxing.BarcodeFormat;
import com.google.zxing.Result;
import com.yuanxin.chooseimage.zxing.camera.CameraManager;
import com.yuanxin.chooseimage.zxing.decoding.CaptureActivityHandler;
import com.yuanxin.chooseimage.zxing.decoding.InactivityTimer;
import com.yuanxin.chooseimage.zxing.view.ViewfinderView;

import java.io.IOException;
import java.util.Map;
import java.util.Vector;

import javax.annotation.Nullable;

import static android.content.Context.AUDIO_SERVICE;
import static android.content.Context.VIBRATOR_SERVICE;

/**
 * Created by LIYAN on 2016/11/15.
 */

public class ScanErCodeManager extends ViewGroupManager<ScanErCodeView> implements SurfaceHolder.Callback{

    private ScanErCodeView scanErCodeView;
    private SurfaceView surfaceView;
    private ViewfinderView viewfinderView;
    private ReactContext reactContext;

    private CaptureActivityHandler handler;
    private Vector<BarcodeFormat> decodeFormats;
    private String characterSet;
    private MediaPlayer mediaPlayer;
    private boolean playBeep;
    private static final float BEEP_VOLUME = 0.10f;
    private boolean vibrate;
    private boolean hasSurface;
    private InactivityTimer inactivityTimer;

    private final int start = 1;
    private final int stop = 2;
    private final int flashOpen = 3;
    private final int flashClose = 4;

    private boolean autoStartRunning;
    private String maskViewBackgroundColor;
    private String maskViewBorderColorColor;
    private int width;
    private int height;
    Camera.Parameters mParameters;
    Camera mCamera;

    @Override
    public String getName() {
        return "ScanCodeView";
    }

    @Override
    protected ScanErCodeView createViewInstance(ThemedReactContext reactContext) {

        CameraManager.init(reactContext.getApplicationContext());

        scanErCodeView = new ScanErCodeView(reactContext);
        surfaceView = scanErCodeView.getSurfaceView();
        viewfinderView = scanErCodeView.getViewfinderView();
        this.reactContext = reactContext;
        hasSurface = false;
        inactivityTimer = new InactivityTimer(reactContext.getCurrentActivity());

        onResume();

        return scanErCodeView;
    }

    /**
     * 是否进入时自动开启扫描
     */
    @ReactProp(name = "autoStartRunning")
    public void SetAutoStartRunning(ScanErCodeView view, @Nullable boolean autoStartRunning){
        this.autoStartRunning = autoStartRunning;
        Log.e("TAG","autoStartRunning---"+autoStartRunning);
    }

    /**
     * 设置描框的背景颜色
     */
    @ReactProp(name = "maskViewBackgroundColor")
    public void SetMaskViewBackgroundColor(ScanErCodeView view, @Nullable String maskViewBackgroundColor){
        this.maskViewBackgroundColor = maskViewBackgroundColor;
        Log.e("TAG","maskViewBackgroundColor---"+maskViewBackgroundColor);
    }

    /**
     * 设置边框的颜色
     */
    @ReactProp(name = "maskViewBorderColorColor")
    public void SetMaskViewBorderColorColor(ScanErCodeView view, @Nullable String maskViewBorderColorColor){
        this.maskViewBorderColorColor = maskViewBorderColorColor;
        Log.e("TAG","maskViewBorderColorColor---"+maskViewBorderColorColor);
    }

    /*
     * 扫描框的宽高
     */
    @ReactProp(name = "scanSize")
    public void SetScanSize(ScanErCodeView view, @Nullable ReadableMap autoStartRunning){
        this.width = autoStartRunning.getInt("width");
        this.height = autoStartRunning.getInt("height");
//        width = px2dip(reactContext,width);
//        height = px2dip(reactContext,height);

        viewfinderView.setWidth(600);
        viewfinderView.setHeight(600);

        Log.e("TAG","SetScanSize---"+"-width-"+width+"-height-"+height);
    }

    /**
     * 根据手机的分辨率从 dp 的单位 转成为 px(像素)
     */
    public static int dip2px(ReactContext context, float dpValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

    /**
     * 根据手机的分辨率从 px(像素) 的单位 转成为 dp
     */
    public static int px2dip(ReactContext context, float pxValue) {
        final float scale = context.getResources().getDisplayMetrics().density;
        return (int) (pxValue / scale + 0.5f);
    }

    /**
     * 打开扫描
     */
    public void start (ScanErCodeView view){}

    /**
     * 关闭当前照像机
     */
    public void stop (ScanErCodeView view){
        onPause();
        onDestroy();
    }

    /**
     * 打开闪光灯
     */
    public void flashOpen (ScanErCodeView view){
        Log.e("TAG","flashOpen");
        CameraManager.get().openFlashLight();
    }

    /**
     * 关闭闪光灯
     */
    public void flashClose (ScanErCodeView view){
        Log.e("TAG","flashClose");
        CameraManager.get().closeFlashLight();
    }

    /**
     * 读取到Code 后回调
     */
    public void SetOnCodeRead(ScanErCodeView view, String CodeRead, String type){
        WritableMap event = Arguments.createMap();
        event.putString("type",type);
        event.putString("data",CodeRead);
        ReactContext reactContext = (ReactContext) view.getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                view.getId(),
                "onCodeRead",
                event);
    }

    /**
     * 出错时调用的接口
     */
    public void SetOnError(ScanErCodeView view, int code, String error){
        WritableMap event = Arguments.createMap();
        event.putInt("code",code);
        event.putString("description",error);
        ReactContext reactContext = (ReactContext) view.getContext();
        reactContext.getJSModule(RCTEventEmitter.class).receiveEvent(
                view.getId(),
                "onError",
                event);
    }

    @Nullable
    @Override
    public Map<String, Integer> getCommandsMap() {
        return MapBuilder.of(
            "start",start,
            "stop",stop,
            "flashOpen",flashOpen,
            "flashClose",flashClose
        );
    }

    @Override
    public void receiveCommand(ScanErCodeView root, int commandId, @Nullable ReadableArray args) {
        switch (commandId){
            case start:
                this.start(root);
                break;
            case stop:
                this.stop(root);
                break;
            case flashOpen:
                this.flashOpen(root);
                break;
            case flashClose:
                this.flashClose(root);
                break;
        }
    }

    public void onResume(){
        Log.e("TAG","onResume");
        SurfaceHolder surfaceHolder = surfaceView.getHolder();
        if (hasSurface) {
            initCamera(surfaceHolder);
        } else {
            surfaceHolder.addCallback(this);
            surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
        }
        decodeFormats = null;
        characterSet = null;

        playBeep = true;
        AudioManager audioService = (AudioManager) reactContext.getSystemService(AUDIO_SERVICE);
        if (audioService.getRingerMode() != AudioManager.RINGER_MODE_NORMAL) {
            playBeep = false;
        }
        initBeepSound();
        vibrate = true;
    }

    public void onPause(){
        Log.e("TAG","onPause");
        if (handler != null) {
            handler.quitSynchronously();
            handler = null;
        }
        CameraManager.get().closeDriver();
    }

    public void onDestroy(){
        Log.e("TAG","onDestroy");
        inactivityTimer.shutdown();
    }

    /*
    成功
     */
    public void handleDecodeSucceed(Result result, Bitmap barcode) {
        inactivityTimer.onActivity();
        playBeepSoundAndVibrate();
        String resultString = result.getText();
        String type = result.getBarcodeFormat().getName();
        if (resultString.equals("")) {
            Log.e("TAG", "Scan failed!");
        }else {
            Log.e("TAG", "Scan sss!"+resultString);
            SetOnCodeRead(scanErCodeView,resultString,type);
//			Intent resultIntent = new Intent();
//			Bundle bundle = new Bundle();
//			bundle.putString("result", resultString);
//			bundle.putParcelable("bitmap", barcode);
//			resultIntent.putExtras(bundle);
//			this.setResult(RESULT_OK, resultIntent);
        }
//        MipcaActivityCapture.this.finish();
    }

    /*
    失败
     */
    public void handleDecodeFailed(){
        SetOnError(scanErCodeView, 40012 ,"Scan failed!");
    }

    private void initCamera(SurfaceHolder surfaceHolder) {
        try {
            CameraManager.get().openDriver(surfaceHolder);
        } catch (IOException ioe) {
            return;
        } catch (RuntimeException e) {
            return;
        }
        if (handler == null) {
            handler = new CaptureActivityHandler(this, decodeFormats,
                    characterSet);
        }
    }

    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        if (!hasSurface) {
            hasSurface = true;
            initCamera(holder);
        }
    }

    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

    }

    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        hasSurface = false;
    }

    public ViewfinderView getViewfinderView() {
        return viewfinderView;
    }

    public Handler getHandler() {
        return handler;
    }

    public void drawViewfinder() {
        viewfinderView.drawViewfinder();

    }

    private void initBeepSound() {
        if (playBeep && mediaPlayer == null) {
            // The volume on STREAM_SYSTEM is not adjustable, and users found it
            // too loud,
            // so we now play on the music stream.
            reactContext.getCurrentActivity().setVolumeControlStream(AudioManager.STREAM_MUSIC);
            mediaPlayer = new MediaPlayer();
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            mediaPlayer.setOnCompletionListener(beepListener);

            AssetFileDescriptor file = reactContext.getResources().openRawResourceFd(
                    R.raw.beep);
            try {
                mediaPlayer.setDataSource(file.getFileDescriptor(),
                        file.getStartOffset(), file.getLength());
                file.close();
                mediaPlayer.setVolume(BEEP_VOLUME, BEEP_VOLUME);
                mediaPlayer.prepare();
            } catch (IOException e) {
                mediaPlayer = null;
            }
        }
    }

    private static final long VIBRATE_DURATION = 200L;

    private void playBeepSoundAndVibrate() {
        if (playBeep && mediaPlayer != null) {
            mediaPlayer.start();
        }
        if (vibrate) {
            Vibrator vibrator = (Vibrator) reactContext.getSystemService(VIBRATOR_SERVICE);
            vibrator.vibrate(VIBRATE_DURATION);
        }
    }

    private final MediaPlayer.OnCompletionListener beepListener = new MediaPlayer.OnCompletionListener() {
        public void onCompletion(MediaPlayer mediaPlayer) {
            mediaPlayer.seekTo(0);
        }
    };


}
